'''
项目名称：产业园区管理运营平台
文件名称：资产数据生成脚本
@Author: 王旭
@Contact: 1643959780@qq.com
@Created: 2025/06/28
@Version: V1.3

@Description:
本脚本用于为产业园区管理运营平台生成资产相关的测试数据。
主要功能包括：
1. 创建唯一的园区
2. 创建多栋楼宇，类型涵盖办公、研发、生产、生活等
3. 为每栋楼创建具有层级关系和唯一性的楼层和房源/单元
   - 楼层标签(actual_label)将采用如 'YF1-5' (研发楼1-5层) 的格式。
   - 单元编号(unit_number)将采用如 'YF1-501' (研发楼1-5层01室) 的格式。
4. 为楼层和单元配备具有规范化名称和编号的设备。
   - 单元设备名称: 'YF1-501 中央空调'
   - 公共设备名称: 'YF1-5-1 消防栓'

@Modifications:
- V1.1: 修正设备创建逻辑，确保与数据库模型一致，不再尝试直接关联楼层。
- V1.2: 根据新的设备模型，在创建设备时添加 building 和 floor 关联。
- V1.3: 引入层级化命名体系，重构楼层、单元及设备的编号与命名逻辑，并优化了内部数据结构。
'''

import os
import sys
import django
import random
import datetime

# --- Start: 动态添加项目根目录到 sys.path ---
# 获取当前脚本文件(init_business.py)的绝对路径
current_script_path = os.path.abspath(__file__)
# 获取脚本所在的目录 (script/)
script_dir = os.path.dirname(current_script_path)
# 获取项目根目录 (back/)，即 script 目录的上级目录
project_root = os.path.dirname(script_dir)
# 将项目根目录添加到 Python 模块搜索路径中
sys.path.append(project_root)
# --- End: 动态添加项目根目录到 sys.path ---

from django.utils import timezone
from faker import Faker

# 设置Django环境
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'smartpark.settings')
django.setup()

# 导入模型
from django.db import transaction, IntegrityError
from assets.models import Park, Building, Floor, Unit, Device
from services.models import Contract

# 初始化Faker
fake = Faker('zh_CN')

# 楼宇类型缩写映射
BUILDING_TYPE_ABBR = {
    "研发楼": "YF",
    "办公楼": "BG",
    "生产厂房": "SC",
    "仓库": "CK",
    "人才公寓": "RC",
    "综合服务中心": "ZH",
}

# 配置参数
CONFIG = {
    "park": {
        "name": "智慧产业园",
        "address": "舜华路1500号",
        "establishment_date": "2020-01-01",
        "total_area": 500000.00
    },
    "buildings": {
        "count": 10,
        "types": {
            "研发楼": {"floors": (8, 15), "area": (8000, 15000), "basement_floors": (1, 2)},
            "办公楼": {"floors": (10, 20), "area": (10000, 20000), "basement_floors": (2, 3)},
            "生产厂房": {"floors": (1, 3), "area": (20000, 50000)},
            "仓库": {"floors": (1, 2), "area": (30000, 60000)},
            "人才公寓": {"floors": (15, 20), "area": (12000, 18000), "basement_floors": (1, 1)},
            "综合服务中心": {"floors": (3, 5), "area": (5000, 10000), "basement_floors": (1, 2)},
        }
    },
    "units_per_floor": {
        "研发楼": (4, 8),
        "办公楼": (6, 10),
        "生产厂房": (1, 2),
        "仓库": (1, 1),
        "人才公寓": (10, 15),
        "综合服务中心": (5, 10),
        "车位": (30, 50)
    },
    "devices": {
        "floor": [
            {"type": "消防栓", "count": 2, "brands": ["天广消防", "闽山消防"]},
            {"type": "应急照明灯", "count": 4, "brands": ["劳士", "敏华"]},
            {"type": "监控摄像头", "count": 2, "brands": ["海康威视", "大华股份"]}
        ],
        "unit": {
            "办公室": [
                {"type": "中央空调", "brands": ["格力", "美的", "大金"]},
                {"type": "智能门禁", "brands": ["海康威视", "熵基科技"]},
                {"type": "饮水机", "brands": ["安吉尔", "沁园"]}
            ],
            "公寓": [
                {"type": "分体式空调", "brands": ["格力", "美的", "海尔"]},
                {"type": "智能门锁", "brands": ["小米", "凯迪仕", "德施曼"]},
                {"type": "热水器", "brands": ["海尔", "A.O.史密斯"]}
            ],
            "厂房": [
                {"type": "工业排风扇", "brands": ["Nedfon", "正野"]},
                {"type": "烟雾报警器", "brands": ["霍尼韦尔", "泛海三江"]}
            ],
             "仓库": [
                {"type": "温湿度传感器", "brands": ["Lattron", "SONBEST"]},
                {"type": "烟雾报警器", "brands": ["霍尼韦尔", "泛海三江"]}
            ],
            "商铺": [
                {"type": "中央空调", "brands": ["格力", "美的", "大金"]},
                {"type": "智能门禁", "brands": ["海康威视", "熵基科技"]},
                {"type": "消防喷淋头", "brands": ["天广消防", "闽山消防"]}
            ]
        }
    }
}

def clear_old_assets_data():
    """清除所有资产相关的数据"""
    print("--- 正在清除旧的资产相关数据... ---")
    Device.objects.all().delete()
    Unit.objects.all().delete()
    Floor.objects.all().delete()
    Building.objects.all().delete()
    Park.objects.all().delete()
    print("旧的资产数据（设备、单元、楼层、楼宇、园区）已清除。")


@transaction.atomic
def create_assets_data():
    """创建所有资产数据"""
    print("--- 开始创建资产数据... ---")

    try:
        # 1. 创建园区
        park = create_park()

        # 2. 创建楼宇
        buildings = create_buildings(park)

        for building in buildings:
            # 3. 创建楼层
            floors = create_floors(building)
            for floor in floors:
                # 4. 创建房源/单元
                units = create_units(floor)
                # 5. 创建楼层设备
                create_floor_devices(floor)
                # 6. 创建房源设备
                create_unit_devices(units)

        print("\n资产数据生成完成！")
        print_statistics()
    except Exception as e:
        print("\n!!! An error occurred during data creation. Transaction will be rolled back. !!!")
        print(f"Error: {e}")
        import traceback
        traceback.print_exc()

def create_park():
    """创建园区"""
    print("\n创建园区...")
    park_config = CONFIG['park']
    now = timezone.now()
    park = Park.objects.create(
        name=park_config['name'],
        address=park_config['address'],
        description=f"{park_config['name']}是一个集研发、办公、生产和生活于一体的现代化智慧产业园区。",
        establishment_date=park_config['establishment_date'],
        total_area=park_config['total_area'],
        contact_info=f"电话: 021-88888888, 邮箱: contact@{fake.domain_name()}",
        created_at=now,
        updated_at=now
    )
    print(f"园区 '{park.name}' 创建成功。")
    return park

def create_buildings(park):
    """创建楼宇"""
    print("\n创建楼宇...")
    buildings = []
    building_types = list(CONFIG['buildings']['types'].keys())
    for i in range(CONFIG['buildings']['count']):
        building_type = random.choice(building_types)
        type_config = CONFIG['buildings']['types'][building_type]
        total_floors = random.randint(*type_config['floors'])
        building_area = random.randint(*type_config['area'])
        now = timezone.now()
        
        building = Building.objects.create(
            park=park,
            name=f"{building_type}-{i+1}号楼",
            total_floors=total_floors,
            building_area=building_area,
            completion_date=fake.date_between(start_date='-5y', end_date='-1y'),
            building_type=building_type,
            structure_type=random.choice(['框架结构', '钢结构']),
            fire_rating=random.choice(['一级', '二级']),
            created_at=now,
            updated_at=now
        )
        buildings.append(building)
        print(f"创建楼宇: {building.name} ({building.building_type}), 共 {building.total_floors} 层")
    return buildings

def create_floors(building):
    """创建楼层"""
    print(f"  ↳ 为 {building.name} 创建楼层...")
    floors = []

    building_type = building.building_type
    try:
        # 从 "研发楼-1号楼" 中提取 "1"
        building_number = ''.join(filter(str.isdigit, building.name.split('-')[1]))
    except (IndexError, ValueError):
        building_number = building.building_id  # Fallback to id
    building_abbr = BUILDING_TYPE_ABBR.get(building_type, "QT")

    # 创建地上楼层
    for i in range(1, building.total_floors + 1):
        now = timezone.now()
        
        # 新的楼层标签逻辑, 例如 YF1-1
        actual_label = f"{building_abbr}{building_number}-{i}"
        
        floor = Floor.objects.create(
            building=building,
            floor_number=i,
            actual_label=actual_label,
            height=random.uniform(3.5, 4.5),
            load_bearing=random.randint(300, 500),
            created_at=now,
            updated_at=now
        )
        floors.append(floor)
    
    # 创建地下楼层
    type_config = CONFIG['buildings']['types'].get(building.building_type, {})
    basement_floors_count = random.randint(*type_config.get('basement_floors', (0, 0)))

    for i in range(1, basement_floors_count + 1):
        now = timezone.now()
        floor_number = -i
        actual_label = f"{building_abbr}{building_number}-B{i}" # 例如 YF1-B1

        floor = Floor.objects.create(
            building=building,
            floor_number=floor_number,
            actual_label=actual_label,
            height=random.uniform(3.0, 3.5),
            load_bearing=random.randint(500, 800),
            created_at=now,
            updated_at=now
        )
        floors.append(floor)

    return floors

def create_units(floor):
    """创建房源/单元"""
    units = []
    building = floor.building
    building_type = building.building_type
    unit_config = CONFIG['units_per_floor']
    
    # 判断单元类型
    if floor.floor_number < 0:
        unit_type = "车位"
    else:
        unit_type_map = {
            "研发楼": "办公室", "办公楼": "办公室",
            "生产厂房": "厂房", "仓库": "仓库",
            "人才公寓": "公寓", "综合服务中心": "商铺"
        }
        unit_type = unit_type_map.get(building_type, "办公室")
    
    config_key = "车位" if unit_type == "车位" else building_type
    if config_key not in unit_config:
        return []
        
    unit_count = random.randint(*unit_config[config_key])
    
    # 提取楼宇编号
    try:
        # 从 "研发楼-1号楼" 中提取 "1"
        building_number = ''.join(filter(str.isdigit, building.name.split('-')[1]))
    except (IndexError, ValueError):
        building_number = building.building_id  # Fallback to id

    building_abbr = BUILDING_TYPE_ABBR.get(building_type, "QT")  # QT for 其他

    for i in range(1, unit_count + 1):
        now = timezone.now()
        
        # 新的单元编号逻辑, 例如 YF1-B101 (研发楼1号楼-B1层01号)
        floor_label_part = f"B{-floor.floor_number}" if floor.floor_number < 0 else str(floor.floor_number)
        unit_number = f"{building_abbr}{building_number}-{floor_label_part}{i:02d}"

        # 根据单元类型设定租金单价和面积
        rental_price = 0
        actual_area = 0
        if unit_type == "车位":
            rental_price = random.randint(300, 800)  # 车位是月租金
            actual_area = random.uniform(12.5, 15.0)
        elif unit_type in ["办公室", "商铺"]:
            rental_price = random.randint(80, 250)   # 每平米月租金
            actual_area = random.randint(50, 300)
        elif unit_type in ["厂房", "仓库"]:
            rental_price = random.randint(30, 90)    # 每平米月租金
            actual_area = random.randint(200, 1000)
        elif unit_type == "公寓":
            rental_price = random.randint(60, 150)   # 每平米月租金
            actual_area = random.randint(30, 100)
        
        building_area = actual_area * random.uniform(1.15, 1.3) if unit_type != "车位" else actual_area
        sale_price = rental_price * random.randint(200, 400) if unit_type != "车位" else rental_price * random.randint(60, 100)

        status = ""
        if unit_type == "车位":
            # 车位的状态简化，并提高"空置"权重，方便后续业务脚本进行租赁
            status = random.choices(['空置', '已售', '不可用'], weights=[8, 1, 1], k=1)[0]
        else:
            status = random.choice(['空置', '意向', '已租', '已售', '装修中', '维修中', '待清洁', '不可用'])

        unit = Unit.objects.create(
            floor=floor,
            building=building,
            unit_number=unit_number,
            actual_area=round(actual_area, 2),
            building_area=round(building_area, 2),
            unit_type=unit_type,
            status=status,
            rental_price=rental_price,
            sale_price=round(sale_price, 2),
            property_fee_standard=round(random.uniform(5, 20), 2),
            orientation=random.choice(['东', '南', '西', '北', '东南', '西南', '东北', '西北']),
            facilities_desc=f"精装修, 配备{random.choice(['中央空调', '独立空调'])}, 高速网络接口",
            created_at=now,
            updated_at=now
        )
        units.append(unit)
    print(f"    ↳ 为 {floor.building.name} {floor.floor_number}层 创建 {unit_count} 个房源...")
    return units

def create_floor_devices(floor):
    """为楼层创建公共设备"""
    devices = []
    device_configs = CONFIG['devices']['floor']

    # 提取楼宇信息用于命名
    building = floor.building
    try:
        building_number_str = ''.join(filter(str.isdigit, building.name.split('-')[1]))
    except (IndexError, ValueError):
        building_number_str = str(building.building_id)
    building_abbr = BUILDING_TYPE_ABBR.get(building.building_type, "QT")

    for config in device_configs:
        for i in range(config['count']):
            now = timezone.now()
            
            device_type = config['type']
            # 新的公共设备命名规范, e.g., YF1-1-1 消防栓
            device_name = f"{building_abbr}{building_number_str}-{floor.floor_number}-{i+1} {device_type}"
            device_number = f"D-{floor.building.building_id}-{floor.floor_id}-0-{random.randint(1000, 9999)}"
            location_desc = f"{floor.building.name} - {floor.floor_number}层 - 公共区域"

            device = Device.objects.create(
                building=floor.building,
                floor=floor,
                unit=None,  # 公共设备不关联具体房源
                device_name=device_name,
                device_number=device_number,
                device_type=device_type,
                brand_model=random.choice(config.get('brands', ['未知品牌'])),
                location_desc=location_desc,
                status='正常',
                purchase_date=fake.date_between(start_date='-3y', end_date='-1y'),
                maintenance_cycle=random.choice([90, 180, 365]),
                created_at=now,
                updated_at=now
            )
            devices.append(device)
    print(f"    ↳ 为 {floor.building.name} {floor.floor_number}层 创建 {len(devices)} 个公共设备。")
    return devices

def create_unit_devices(units):
    """为房源创建内部设备"""
    devices_created_count = 0
    for unit in units:
        # 获取适用于该单元类型的所有设备配置
        device_configs_for_unit_type = CONFIG['devices']['unit'].get(unit.unit_type)

        if device_configs_for_unit_type:
            # 为该单元类型创建所有配置的设备，而不仅仅是随机选择一个
            for device_config in device_configs_for_unit_type:
                now = timezone.now()
                
                device_type = device_config['type']
                device_name = f"{unit.unit_number} {device_type}"
                device_number = f"D-{unit.building.building_id}-{unit.floor.floor_id}-{unit.unit_id}-{random.randint(1000, 9999)}"
                location_desc = f"{unit.building.name} - {unit.floor.floor_number}层 - {unit.unit_number}"

                Device.objects.create(
                    building=unit.building,
                    floor=unit.floor,
                    unit=unit,
                    device_name=device_name,
                    device_number=device_number,
                    device_type=device_type,
                    brand_model=random.choice(device_config.get('brands', ['未知品牌'])),
                    location_desc=location_desc,
                    status='正常',
                    purchase_date=fake.date_between(start_date='-2y', end_date='-6m'),
                    maintenance_cycle=random.choice([180, 365]),
                    created_at=now,
                    updated_at=now
                )
                devices_created_count += 1
    
    # 更新日志，使其更准确地反映创建的设备总数
    print(f"    ↳ 为房源创建了 {devices_created_count} 个内部设备。")

def print_statistics():
    """打印数据统计信息"""
    print("\n=== 数据统计 ===")
    print(f"园区总数: {Park.objects.count()}")
    print(f"楼宇总数: {Building.objects.count()}")
    print(f"楼层总数: {Floor.objects.count()}")
    print(f"房源总数: {Unit.objects.count()}")
    print(f"设备总数: {Device.objects.count()}")
    
    print("\n楼宇类型统计:")
    building_types = {}
    for building in Building.objects.all():
        building_types[building.building_type] = building_types.get(building.building_type, 0) + 1
    for b_type, count in building_types.items():
        print(f"- {b_type}: {count}栋")

    print("\n设备类型统计:")
    device_types = {}
    for device in Device.objects.all():
        device_types[device.device_type] = device_types.get(device.device_type, 0) + 1
    for d_type, count in device_types.items():
        print(f"- {d_type}: {count}个")

if __name__ == "__main__":
    clear_old_assets_data()
    create_assets_data() 